package com.gitee.gen.common;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 简易内存缓存：LRU + 10 分钟过期（最后一次访问）
 */
public class MemCache<K, V> {

    private final int maxSize;
    private final long expireMillis;

    /* 存数据 + 时间戳 */
    private static class ValueWrapper<V> {
        V value;
        long lastAccess;

        ValueWrapper(V v) {
            this.value = v;
            this.lastAccess = System.currentTimeMillis();
        }
    }

    private final Map<K, ValueWrapper<V>> map;
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public MemCache(int maxSize, long expireMinutes) {
        this.maxSize = maxSize;
        this.expireMillis = expireMinutes * 60 * 1000;

        // LinkedHashMap 实现 LRU
        this.map = new LinkedHashMap<K, ValueWrapper<V>>(16, 0.75f, true) {
            @Override
            protected boolean removeEldestEntry(Map.Entry<K, ValueWrapper<V>> eldest) {
                return size() > MemCache.this.maxSize;
            }
        };
    }

    public void put(K key, V value) {
        lock.writeLock().lock();
        try {
            map.put(key, new ValueWrapper<>(value));
        } finally {
            lock.writeLock().unlock();
        }
    }

    public V get(K key) {
        lock.readLock().lock();
        try {
            ValueWrapper<V> w = map.get(key);
            if (w == null) return null;
            // 过期判断
            if (System.currentTimeMillis() - w.lastAccess > expireMillis) {
                lock.readLock().unlock();
                lock.writeLock().lock();
                try {
                    map.remove(key);
                } finally {
                    lock.writeLock().unlock();
                }
                return null;
            }
            // 更新时间戳
            w.lastAccess = System.currentTimeMillis();
            return w.value;
        } finally {
            lock.readLock().unlock();
        }
    }

    public V remove(K key) {
        lock.writeLock().lock();
        try {
            ValueWrapper<V> w = map.remove(key);
            return w == null ? null : w.value;
        } finally {
            lock.writeLock().unlock();
        }
    }
}